/**
 * Created by strowsoul on 2017/7/20.
 */
(function(){

    function ZookeeperRegister(){
        var PATH = "/motor";
        var devicesPath = PATH+"/devices";
        var servicesPath = PATH+"/services";
        var ZkClient =Java.type("org.I0Itec.zkclient.ZkClient");
        var IZkDataListener = Java.type("org.I0Itec.zkclient.IZkDataListener");
        var IZkChildListener = Java.type("org.I0Itec.zkclient.IZkChildListener");
        var Serializable = Java.type("java.io.Serializable");
        var Motor = Java.type("com.motor.core.Motor");

        var zc = new ZkClient($current.zookeeper);
        this.services = {};
        this.devices = {};
        this.tmpServices=[];
        var $this = this;
        if(!zc.exists(devicesPath)){
            zc.createPersistent(devicesPath, true);
        }
        this.resetDevicesNode= function(){
            // 重置设备节点
            if(zc.exists(devicesPath)){
                zc.deleteRecursive(devicesPath);
            }
            zc.createPersistent(devicesPath, true);
        }
        // master会用到
        this.installDevices= function(devices){
            // 创建已有的设备列表节点,以及设备下的服务
            for(var i in devices){
                var device = devices[i];
                var devicePath = devicesPath+"/"+device.host+"-"+device.port;
                if(!zc.exists(devicePath)){
                    zc.createPersistent(devicePath, true);
                }
                INFO("[注册设备:"+devicePath+"]")

                var services = [];
                for(var i in device.services){
                    services.push(device.services[i]);
                }
                this.devices[device.host+"-"+device.port]={
                    services : services
                };
                for (var j in services){
                    if(!zc.exists(devicePath+"/"+services[j])){
                        zc.createPersistent(devicePath+"/"+services[j], true);
                    }
                }
            }
        }
        this.installServices= function(rels){
            // 给所有的action  和 gateway 的 relative 注册成服务节点
            for(var i in rels){
                var service = rels[i];
                var servicePath = servicesPath+"/"+service.key;
                var b = ["action","gateway"].indexOf(service.type);
                if(b>=0){

                    if(!zc.exists(servicePath)){
                        zc.createPersistent(servicePath, true);
                    }
                    var data = {};
                        data.type=service.type;
                        data.isCache=service.isCache;
                    zc.writeData(servicePath,JSON.stringify(data));
                }
            }
        }
        this.regToCenter= function(host,port,servers){
            this.removeServices(host,port,servers); // 清除新的服务列表中没有的服务
            // 把本设备需要提供的服务注册到zookeeper
            if(!zc.exists(servicesPath)){
                zc.createPersistent(servicesPath, true);
            }
            for(var i in servers){
                var servicePath = servicesPath+"/"+servers[i];
                if(!zc.exists(servicePath)){
                    // 打印日志，但不抛出异常
                    ERROR("节点不存在:"+servicePath);
                }else{
                    //把自己注册到个服务节点下,等待调用
                    var serviceDevicePath = servicePath+"/"+host+"-"+port;
                    if(zc.exists(serviceDevicePath)){
                        zc.delete(serviceDevicePath)
                    }
                    zc.createEphemeral(serviceDevicePath);
                    INFO("注册服务:"+servers[i]);
                }

            }
            if(!$this.devices[host+"-"+port]){
                $this.devices[host+"-"+port] ={};
            }
            $this.devices[host+"-"+port].tmpServices = servers;
        }
        this.removeServices = function(host,port,list){
            if(!this.devices[host+"-"+port]){
                return;
            }
            var services = this.devices[host+"-"+port].tmpServices;
            var tmplist = [];
            for(var i in services){
                if(list.indexOf(services[i])<0){
                    tmplist.push(services[i]);
                };
            }
            for(var i in tmplist){
                var servicePath = servicesPath+"/"+tmplist[i];
                if(zc.exists(servicePath)){
                    //master提供的服务暂时是不发生变化的
                    //把自己注册到个服务节点下,等待调用
                    var serviceDevicePath = servicePath+"/"+host+"-"+port;
                    if(zc.exists(serviceDevicePath)){
                        zc.delete(serviceDevicePath);
                        INFO("取消服务:"+tmplist[i]);
                    }
                }

            }
        }
        this.getData = function(path){
            return zc.readData(path);
        }
        this.changeDeviceServices = function(device){
            var devicePath = devicesPath+"/"+device.host+"-"+device.port;
            if(device.services){
                var list;
                if(!zc.exists(devicePath)){
                    zc.createPersistent(devicePath, true);
                }else{
                    list = zc.getChildren(devicePath);
                }

                //全部刪除
                if(list != undefined  && list != null && list.length>0){
                    for(var i in list){
                        zc.deleteRecursive(devicePath+"/"+list[i]);
                    }
                }

                //重新添加
                for(var i in device.services){
                    if(!zc.exists(devicePath+"/"+device.services[i])){
                        zc.createPersistent(devicePath+"/"+device.services[i], true);
                        INFO("更新节点:"+devicePath+"/"+device.services[i]);
                    }
                }
            }
        }
        this.getDeviceRandom = function(list){
            var totalW = 0;
            for(var i in list){
                totalW+= list[i].weight;
            }
            var tempW = Math.random()*totalW;
            for(var i in list){
                tempW -= list[i].weight;
                if(tempW<=0){
                    return list[i];
                }
            }
        }
        this.getDeviceForService = function(serviceName){
            var service= $this.services[serviceName]
            var device= {};
            if(!service){
                service= {
                    devices : zc.getChildren(servicesPath+"/"+serviceName)
                }
                $this.services[serviceName] = service ;
            }
            if(service && service.devices){
                if(service.devices.length ==1){
                    var str =  service.devices[0];
                    var arr = str.split("-");
                    device.host = arr[0];
                    device.port = arr[1];
                }else if( service.devices.length > 1){
                    var tmpDevices = [];
                    var ds = service.devices;
                    for(var i in ds){
                        var str =  ds[i];
                        var arr = str.split("-");
                        tmpDevices.push({
                            host:arr[0],
                            port:arr[1],
                            weight:100
                        })
                    }
                    return this.getDeviceRandom(tmpDevices);
                }

            }
            return device;
        }
        this.getServicesForDevice= function(host,port){
            var key= host+"-"+port;
            var device = this.devices[key];
            if(!device){
                device = {
                    host:host,
                    port:port,
                    services:zc.getChildren(devicesPath+"/"+key)
                }
                this.devices[key] = device;
            }
            return device.services;
        }
        this.listenerDeviceConfig = function(host,port){
            // 监听自己的服务配置变化,slave用
            var $this = this;
            var selfPath= devicesPath+"/"+host+"-"+port;
            zc.subscribeChildChanges(selfPath,new IZkChildListener({
                handleChildChange:function(path,list) {
                    print("变更节点为:" + path + "  变更数据为" + list.toString());
                    $this.removeServices(host,port);
                    $this.regToZookeeper(host,port,list);
                }
            }));
        }
        this.readServiceData = function(serviceName){
            var data = zc.readData(servicesPath+"/"+serviceName);
            return JSON.parse(data);
        }
    }
    ZookeeperRegister.prototype = RegisterCenter;
    var $regCenter = new RegisterCenter();
    return $regCenter;
})()